package com.my.collection.stack.v17;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by Scarlett on 2018/9/3 0003.
 * <p>
 * 栈，从栈顶推入数据，从栈顶弹出数据
 */
public class Stack<E> {
    private Node<E> top;

    private AtomicBoolean lock = new AtomicBoolean(false);

    /**
     * 推入元素
     *
     * @param e
     */
    public void push(E e) {
        for (; ; ) {
            if (this.lock.compareAndSet(false, true)) {
                try {
                    Node<E> node = new Node<>(e, null);
                    Node<E> t = this.top;
                    this.top = node;
                    node.next = t;

                    return;
                } finally {
                    this.lock.set(false);
                }
            }
        }
    }

    /**
     * 弹出元素
     *
     * @return
     */
    public E pop() {
        for (; ; ) {
            if (this.lock.compareAndSet(false, true)) {
                try {
                    Node<E> top = this.top;
                    if (top == null) {
                        return null;
                    }

                    E e = top.e;
                    this.top = top.next;

                    return e;
                } finally {
                    this.lock.set(false);
                }
            }
        }
    }

    /**
     * 栈的元素个数
     *
     * @return
     */
    public int size() {
        int size = 0;
        for (Node<E> node = this.top; node != null; node = node.next) {
            size += 1;
        }
        return size;
    }


    private static class Node<E> {
        private E e;
        private Node<E> next;//下一个节点

        Node(E e, Node<E> next) {
            this.e = e;
            this.next = next;
        }
    }
}

